﻿using System;
using System.Collections.Generic;
using System.Text;

namespace DesignPatterns
{
    /// <summary>
    /// Implementation of the Singleton Pattern. The singleton pattern is one of 
    /// the best-known patterns in software engineering. Essentially, a singleton 
    /// is a class which only allows a single instance of itself to be created, and 
    /// usually gives simple access to that instance. Most commonly, singletons 
    /// don't allow any parameters to be specified when creating the instance - as 
    /// otherwise a second request for an instance but with a different parameter 
    /// could be problematic!
    /// http://www.yoda.arachsys.com/csharp/singleton.html
    /// </summary>
    /// <typeparam name="T">type of the singleton</typeparam>
    public sealed class Singleton<T> where T : class, new()
    {
        static T m_Instance = null;

        /// <summary>
        /// this variable is used for thread safety
        /// </summary>
        static readonly object m_Padlock = new object();

        /// <summary>
        /// returns the reference of the singleton
        /// </summary>
        public static T Instance
        {
            get
            {
                lock (m_Padlock)
                {
                    if (m_Instance == null)
                    {
                        m_Instance = new T();
                    }
                    return m_Instance;
                }
            }
        }
    }
    public sealed class Singleton2<T> where T : class, new()
    {
        static T m_Instance = null;

        /// <summary>
        /// this variable is used for thread safety
        /// </summary>
        static readonly object m_Padlock = new object();

        /// <summary>
        /// returns the reference of the singleton
        /// </summary>
        public static T Instance
        {
            get
            {
                lock (m_Padlock)
                {
                    if (m_Instance == null)
                    {
                        m_Instance = new T();
                    }
                    return m_Instance;
                }
            }
        }
    }
}

